package org.dromara.quick.chat.service.impl;

import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.utils.IdGenerator;
import org.dromara.common.model.enums.im.AuditStatusEnums;
import org.dromara.common.mongo.dto.GeoDTO;
import org.dromara.common.mongo.wrapper.WrapperCriteria;
import org.dromara.common.mongo.wrapper.WrapperUpdate;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.quick.chat.domain.ImSocialPost;
import org.dromara.quick.chat.model.bo.create.ImSocialPostBO;
import org.dromara.quick.chat.model.bo.query.ImSocialCommentQueryBO;
import org.dromara.quick.chat.model.bo.query.ImSocialPostQueryBO;
import org.dromara.quick.chat.model.vo.ImSocialCommentVO;
import org.dromara.quick.chat.model.vo.ImSocialPostBasicVO;
import org.dromara.quick.chat.model.vo.ImSocialPostDetailVO;
import org.dromara.quick.chat.model.vo.ImSocialPostVO;
import org.dromara.quick.chat.service.ImSocialCommentService;
import org.dromara.quick.chat.service.ImSocialPostService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.vo.RemoteUserBasicVO;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author Stars
* @description 针对表【im_social_post(社交软件中的动态表，用于存储用户发布的动态相关信息)】的数据库操作Service实现
* @createDate 2025-03-06 22:01:35
*/
@RequiredArgsConstructor
@Service
public class



ImSocialPostServiceImpl implements ImSocialPostService {


    private final MongoTemplate mongoTemplate;

    private final Converter converter;

    private final ImSocialCommentService imSocialCommentService;

    @DubboReference
    private final RemoteUserService remoteUserService;


    @Override
    public List<ImSocialPostBasicVO> selectImSocialPostListByUserId(Long userId, Long pageSize) {
        List<ImSocialPost> imSocialPosts = mongoTemplate.find(Query.query(new WrapperCriteria<ImSocialPost>().and(ImSocialPost::getUserId).is(userId)).limit(Math.toIntExact(pageSize)), ImSocialPost.class);
        return converter.convert(imSocialPosts, ImSocialPostBasicVO.class);
    }

    @Override
    public Long postTotal(Long userId) {
        return mongoTemplate.count(Query.query(new WrapperCriteria<ImSocialPost>().and(ImSocialPost::getUserId).is(userId)),ImSocialPost.class);
    }

    @Override
    public void addSocialPost(ImSocialPostBO imSocialPostBO) {
        Long userId = LoginHelper.getUserId();

        ImSocialPost imSocialPost = new ImSocialPost();
        imSocialPost.setId(IdGenerator.getId());
        imSocialPost.setUserId(userId);
        imSocialPost.setPostContent(imSocialPostBO.getPostContent());
        imSocialPost.setImageSet(imSocialPostBO.getImageSet());
//        imSocialPost.setExpirationTime();
        imSocialPost.setLikeCount(0);
        imSocialPost.setCommentCount(0);
        imSocialPost.setShareCount(0);
        imSocialPost.setLocation(imSocialPostBO.getGeoDTO());
        imSocialPost.setAddressName(imSocialPostBO.getAddressName());
        imSocialPost.setTopics(imSocialPostBO.getTopics());
        imSocialPost.setMentionedFriends(imSocialPostBO.getMentionedFriends());
        imSocialPost.setCommunityId(imSocialPostBO.getCommunityId());
        imSocialPost.setReviewStatus(AuditStatusEnums.UNAUDITED.getCode());
        imSocialPost.setCreateTime(new Date());
        imSocialPost.setStrangerVisible(imSocialPostBO.getStrangerVisible());
        mongoTemplate.save(imSocialPost);
    }

    @Override
    public List<ImSocialPostVO> listSocialPost(ImSocialPostQueryBO imSocialPostQueryBO) {
        List<ImSocialPost> imSocialPosts = mongoTemplate.find(new Query().with(Sort.by(Sort.Direction.DESC, "createTime"))
            .skip(imSocialPostQueryBO.getFirstNum())
            .limit(imSocialPostQueryBO.getPageSize()), ImSocialPost.class);
        List<ImSocialPostVO> imSocialPost = converter.convert(imSocialPosts, ImSocialPostVO.class);
        this.handleUserInfo(imSocialPost);
        return imSocialPost;
    }

    @Override
    public List<ImSocialPostVO> listSocialPostByUserId(ImSocialPostQueryBO imSocialPostQueryBO) {
        if (imSocialPostQueryBO.getUserId() == null){
            imSocialPostQueryBO.setUserId(LoginHelper.getUserId());
        }

        List<ImSocialPost> imSocialPosts = mongoTemplate.find(new Query(new WrapperCriteria<ImSocialPost>().and(ImSocialPost::getUserId).is(imSocialPostQueryBO.getUserId())).with(Sort.by(Sort.Direction.DESC, "createTime")), ImSocialPost.class);
        List<ImSocialPostVO> imSocialPost = converter.convert(imSocialPosts, ImSocialPostVO.class);
        this.handleUserInfo(imSocialPost);
        return imSocialPost;
    }

    /**
     * 距离有近到远搜索
     *
     * @param imSocialPostQueryBO
     * @return
     */
    @Override
    public List<ImSocialPostVO> findEntitiesByLocation(ImSocialPostQueryBO imSocialPostQueryBO) {
        GeoDTO geoDTO = GeoDTO.defaultGeo(GeoDTO.defaultGeo(imSocialPostQueryBO.getGeoDTO()));
        Pageable pageable = PageRequest.of(imSocialPostQueryBO.getPageNum(), imSocialPostQueryBO.getPageSize());
        // 创建 NearQuery 对象，指定查询的中心点和分页信息
        NearQuery nearQuery = NearQuery.near(new GeoJsonPoint(geoDTO.getX(), geoDTO.getY()))
            .maxDistance(Double.MAX_VALUE)
            .query(new Query().with(pageable));
        // 执行查询，返回包含距离信息的结果列表
        List<GeoResult<ImSocialPost>> content = mongoTemplate.geoNear(nearQuery, ImSocialPost.class).getContent();
        List<ImSocialPost> imSocialPostStream = content.stream().map(GeoResult::getContent).collect(Collectors.toUnmodifiableList());
        List<ImSocialPostVO> imSocialPost = converter.convert(imSocialPostStream, ImSocialPostVO.class);
        this.handleUserInfo(imSocialPost);
        return imSocialPost;
    }

    @Override
    public void like(Long socialPostId) {
        WrapperCriteria<ImSocialPost> wrapperCriteria = new WrapperCriteria<ImSocialPost>().and(ImSocialPost::getId).is(socialPostId);
        mongoTemplate.updateFirst(Query.query(wrapperCriteria), new WrapperUpdate<ImSocialPost>().inc(ImSocialPost::getLikeCount,1), ImSocialPost.class);
    }

    @Override
    public ImSocialPostDetailVO detailSocialComment(Long socialPostId, PageQuery pageQuery) {
        ImSocialPost templateOne = mongoTemplate.findOne(new Query(new WrapperCriteria<ImSocialPost>().and(ImSocialPost::getId).is(socialPostId)), ImSocialPost.class);
        if (templateOne == null) {
            return null;
        }
        // 查询用户信息
        RemoteUserBasicVO remoteUserBasic = remoteUserService.selectUserBasicById(templateOne.getUserId());
        ImSocialPostDetailVO imSocialPostDetailVO = converter.convert(templateOne, ImSocialPostDetailVO.class);
        if (remoteUserBasic != null) {
            imSocialPostDetailVO.setAvatar(remoteUserBasic.getAvatar());
            imSocialPostDetailVO.setNickName(remoteUserBasic.getNickName());
            imSocialPostDetailVO.setUserId(remoteUserBasic.getUserId());
        }

        ImSocialCommentQueryBO build = ImSocialCommentQueryBO.builder().socialPostId(templateOne.getId()).build();
        build.setPageNum(pageQuery.getPageNum());
        build.setPageSize(pageQuery.getPageSize());
        List<ImSocialCommentVO> children = imSocialCommentService.list(build);
        imSocialPostDetailVO.setChildren(children);
        return imSocialPostDetailVO;
    }

    @Override
    public void commentLike(Long socialPostId) {
        WrapperCriteria<ImSocialPost> wrapperCriteria = new WrapperCriteria<ImSocialPost>().and(ImSocialPost::getId).is(socialPostId);
        mongoTemplate.updateFirst(Query.query(wrapperCriteria), new WrapperUpdate<ImSocialPost>().inc(ImSocialPost::getCommentCount,1), ImSocialPost.class);
    }

    /**
     * 处理用户的信息
     */
    private void handleUserInfo(List<ImSocialPostVO> imSocialPost) {
        if (CollectionUtils.isEmpty(imSocialPost)) {
            return;
        }
        List<RemoteUserBasicVO> remoteUserBasicVOS = remoteUserService.selectListUserBasicByIds(imSocialPost.stream().map(ImSocialPostVO::getUserId).distinct().collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(remoteUserBasicVOS)) {
            return;
        }
        // 使用 Stream 和 Collectors.toMap 创建映射
        Map<Long, RemoteUserBasicVO> userMap = remoteUserBasicVOS.stream()
            .collect(Collectors.toMap(RemoteUserBasicVO::getUserId, user -> user));
        for (ImSocialPostVO imSocialPostVO : imSocialPost) {
            RemoteUserBasicVO remoteUserBasicVO = userMap.get(imSocialPostVO.getUserId());
            if (remoteUserBasicVO == null) {
                continue;
            }
            imSocialPostVO.setNickName(remoteUserBasicVO.getNickName());
            imSocialPostVO.setAvatar(remoteUserBasicVO.getAvatar());
        }
    }
}
